/*
 * message.h
 *
 *      Author: pablo
 *
 *      El objetivo de este modulo es definir las estructuras de mensajes q navegaran por la red
 *      en la aplicacion y que pueden manejar los demas modulas
 */

#ifndef MESSAGE_H_
#define MESSAGE_H_

//Cabeceras a incluir
#include <netinet/in.h>
#include <sys/param.h>
#include <netdb.h>
#include <unistd.h>
#include <arpa/inet.h>
#include "constantes.h"
#include "configuracion.h"
#include "variables.h"
#include "listas.h"
#include "conexion.h"





// cabecera basica de un mensaje
struct messageHeader{
	unsigned char GUID[LENGTH_MESSAGE_ID];
	unsigned char ttl;
	unsigned char hops;
	unsigned char payload_type;
	unsigned int payload_length;
	// puede ser una query, un query_hit, o un bye y como cada uno cambia se hace un puntero generico
	void *payload; // esto no lo he probado nunca pero SAN GOOGLE dice q es un puntero a algo generico, incluso a NULO si fuese necesacio
};

/* mensaje basico del protocolo */
struct message{
	unsigned int sockfd;
	struct messageHeader *header;
};


// mensaje tipo: query
struct queryMessage{
	unsigned short int min_speed; // velocidad minima
	char *search; //criterio de busqueda
};

// mensaje tipo: query_hit
struct queryHitMessage{
	unsigned char numExitos; // numero de exitos
	in_port_t port; // puerto
	in_addr_t ip; // direccion ip
	unsigned int speed;
	struct resultSet *result; 	// resultset de la consulta, es una cola de resultados simplemente enlazada
	unsigned char serventID[LENGTH_MESSAGE_ID];
};

// mensaje tipo: bye
struct byeMessage{
	unsigned char code[LENGTH_BYE_CODE];
	char blank; // un caracter identificativo de bye con valor: 0x20
	char *description;
};

// estructura de apoyo, contiene los resultado de la query (resulSet)
struct resultSet{
	unsigned int tamArchivo; //para permitir mayor tamaño, xq siempre >0
	char *indiceArchivo;  // indizacion del archivo
	char *nombreArchivo; //nombre del archivo
	struct resultSet *next; //puntero al siguiente resulset
	/*
	 * ya que hay una lista de resultados buscar algo para recorrer la lista no estaria nada mal,
	 * algo asi como un modulo externo que pasada una lista sea capaz de navegar por ella,
	 * BUSCAR EN INTERNETE !!!
	 */
};


/*
 * Metodos asociados a los mensajes, estos metodos no se preocupan de la conexion que es gestionada
 * por otro modulo sino que unicamente se preocupa de preparar la informacion a enviar o de preparar
 * la recibida
 *
 * como existen varias conexiones hay que indicar el descriptor de la conexion por
 *  la que se lo queremos enviar
 *
 *  prepararXXXXXX: escribe y envia por socket la estructura q corresponda
 *  leerXXXXXX: lee del socket y lo mete en la estructura q corresponda
 */
int prepararCabecera(int soc, struct messageHeader *cabecera);
int leerCabecera( int soc, struct messageHeader *cabecera );

int prepararQuery(int soc, struct queryMessage *consulta);
int leerQuery(int soc, struct queryMessage *consulta, size_t resto);

int prepararQueryHit(int soc, struct queryHitMessage *exito);
int leerQueryHit(int soc, struct queryHitMessage *exito, size_t resto);

int prepararResultSet ( int soc, struct resultSet *s);
int leerResultSet ( int soc, struct resultSet *set, size_t n);

int prepararBye(int soc, struct byeMessage *bye);
int leerBye(int soc, struct byeMessage *bye, size_t n);

int enviarMensaje (int sockfd, struct message *m);
struct message * recibirMensaje (int sockfd);


/*
 * antiormente se mostraron los mensajes propios
 * ahora se definen aquellos en los que interviene el sercivio HTTP
 */

int pedirConexion(int soc); //peticion de inicio de sesion con un servidor
int enviarRespuestaServidor(int soc); // respuesta a un inicio de sesion
int enviarRespuestaCliente(int soc); //respuesta a una peticion de inicio de sesion del servidor


int pedirArchivo (int soc, char *indiceArchivo, char *nombreArchivo); //para pedir archivo a servidor

//TODO el siguiente SIN HACER AUN
int responderPeticionArchivo (int soc, int indiceArchivo, char *estado, char *estadoMens); //respuesta a pet de archivo

int envioUpdateRequest(int soc); //envio de update request al S. RowebCache

int envioHostfileRequest (int soc); //envio de un hostfile request al S. Rowebcache

// respuesta a los mensajes de envio
int recibirRespuestaConexion(int soc);
int recibirRespuestaServidor(int soc);
int recibirRespuestaCliente(int soc);

int recibirGetMessage (int soc, char *nombreArchivo); //recivo pedirArchivo

int responderPeticionArchivo (int soc, int indiceArchivo, char *estado, char *estadoMens);

int recibirRespuestaUpdate(int soc);

int recibirRespuestaHostfileRequest (int soc);

char *recibirCadena (int soc, size_t tam, char sep);
int mensajeExpirado(struct message* m);
#endif /* MESSAGE_H_ */
